(* CompUnit → FuncDef+

 Stmt → Block ∣ “;” ∣ Expr “;” ∣ ID “=” Expr “;”
 ∣ “int” ID “=” Expr “;”
 ∣ “if” “(” Expr “)” Stmt (“else” Stmt)?
 ∣ “while” “(” Expr “)” Stmt
 ∣ “break” “;” ∣ “continue” “;” ∣ “return” “;”
 
 Block → “{” Stmt∗ “}”

 FuncDef → (“int” ∣ “void”) ID “(” (Param (“,” Param)∗)? “)” Block

 Param → “int” ID

 Expr → LOrExpr

 LOrExpr → LAndExpr ∣ LOrExpr “||” LAndExpr

 LAndExpr → RelExpr ∣ LAndExpr “&&” RelExpr

 RelExpr → AddExpr
 ∣ RelExpr (“<” ∣ “>” ∣ “<=” ∣ “>=” ∣
 “==” ∣ “!=”) AddExpr

 AddExpr → MulExpr
 ∣ AddExpr (“+” ∣ “-”) MulExpr

 MulExpr → UnaryExpr
 ∣ MulExpr (“*” ∣ “/” ∣ “%”) UnaryExpr

 UnaryExpr → PrimaryExpr
 ∣ (“+” ∣ “-” ∣ “!”) UnaryExpr

PrimaryExpr → ID ∣ NUMBER ∣ “(” Expr “)”
 ∣ ID “(” (Expr (“,” Expr)∗)? “)” *)
 
(* 位置信息类型 (用于错误报告) *)

(* 类型系统 *)
type ty =  
  | TInt
  | TVoid

(* 一元运算符 *)
type unary_op = 
  | UPlus    (* + *)
  | UMinus   (* - *)
  | UNot     (* ! *)

(* 二元运算符 *)
type binary_op = 
  | Add      (* + *)
  | Sub      (* - *)
  | Mul      (* * *)
  | Div      (* / *)
  | Mod      (* % *)
  | LT       (* < *)
  | GT       (* > *)
  | LE       (* <= *)
  | GE       (* >= *)
  | EQ       (* == *)
  | NE       (* != *)
  | And      (* && *)
  | Or       (* || *)

  (* Token 类型定义 *)
type token =
  | T_INT of int
  | T_ID of string
  | T_TY of ty
  | T_UNARY of unary_op
  | T_ADD | T_SUB | T_MUL | T_DIV | T_MOD
  | T_LT | T_GT | T_LE | T_GE | T_EQ | T_NE | T_AND | T_OR
  | T_LPAREN | T_RPAREN
  | T_LBRACE | T_RBRACE
  | T_SEMI
  | T_COMMA
  | T_ASSIGN
  | T_IF | T_ELSE
  | T_WHILE
  | T_BREAK | T_CONTINUE
  | T_RETURN
  | T_EOF

(* 表达式 *)
type expr = 
  | Num of int       (* 整数常量 *)
  | ID of string               (* 变量引用 *)
  | Unary of unary_op * expr     (* 一元表达式 *)
  | Binary of binary_op * expr * expr (* 二元表达式 *)
  | Call of string * expr list    (* 函数调用 *)
  | Paren of expr                (* 括号表达式 *)
  
(* 语句 *)
type stmt = 
  | Block of stmt list           (* { ... } *)
  | Empty                        (* 空语句 ; *)
  | ExprStmt of expr             (* 表达式语句 *)
  | Assign of string * expr       (* 变量赋值 *)
  | Declare of string * expr      (* 变量声明 int id = expr; *)
  | If of expr * stmt * stmt option (* if语句 *)
  | While of expr * stmt         (* while循环 *)
  | Break                        (* break *)
  | Continue                     (* continue *)
  | Return of expr option                 (* return *)

(* 函数参数 *)
type param = {
  pty : ty;
  pid : string;
}

(* 函数定义 *)
type func_def = {
  ret_ty : ty;
  name : string;
  params : param list;
  body : stmt;  (* 函数体是一个块语句 *)
}

(* 完整程序 *)
type program = func_def list